package com.glsc.ngateway.common.api.common.utils;


import com.glsc.ngateway.common.api.common.enums.Constant;
import com.glsc.ngateway.common.api.common.enums.DictConstant;
import com.glsc.ngateway.common.api.common.ex.GatewayException;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import javax.persistence.Column;
import javax.persistence.Table;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author zhouzp
 * @date 2020/6/1
 * 工具类
 */
public class CommonUtils {

    private static Logger logger = LoggerFactory.getLogger(CommonUtils.class);


    /**
     * 校验邮箱合法性
     *
     * @param email 邮箱地址
     * @throws IOException
     */
    public static Boolean validEmail(String email) {
        if (StringUtils.isBlank(email)) {
            return false;
        }
        String pat = ".+@\\w+(\\.\\w{1,10})+";
        Pattern p = Pattern.compile(pat);
        Matcher m = p.matcher(email);
        if (!m.matches()) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 校验邮箱合法性
     *
     * @param emailStr 邮箱地址字符串，多个以特定字符区分
     * @param splitStr 分隔字符串
     * @return 返回字符串列表，如果一个邮箱都没有则返回空列表，不会返回null
     * @throws IOException
     */
    public static List<String> mailList(String emailStr, String splitStr) {
        List<String> mailList = new ArrayList<>();
        if (StringUtils.isBlank(emailStr)) {
            return mailList;
        }
        if (splitStr.equals("，") || splitStr.equals(",")) {
            splitStr = ",";
            emailStr = emailStr.replace("，", ",");
        }
        String[] emailArray = emailStr.split(splitStr);
        for (String email : emailArray) {
            mailList.add(StringUtils.trim(email));
        }

        return mailList;

    }

    /**
     * 将日期字符串转换为日期date
     *
     * @param strDate  日期字符串
     * @param formatter 日期格式
     * @return 返回两个日期之间间隔的天数
     */
    public static Date dateStrToDate(String strDate,SimpleDateFormat formatter) {
        if(StringUtils.isEmpty(strDate)||formatter==null){
            return null;
        }

        ParsePosition pos = new ParsePosition(0);
        Date strToDate = formatter.parse(strDate, pos);
        return strToDate;
    }

    /**
     * 将时间字符串转换为时间对象
     *
     * @param timeStr 日期字符串
     * @return 返回两个日期之间间隔的天数
     */
    public static LocalDateTime timeStrToLocalDateTime(String timeStr) {
        if (StringUtils.isEmpty(timeStr)) {
            return null;
        }
        try {

            DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

            LocalDateTime localDateTime = LocalDateTime.parse(timeStr, timeFormatter);
            return localDateTime;
        } catch (Exception e) {
            logger.error("日期解析错误", e);
        }

        return null;
    }



    /**
     * 将日期字符串转换为日期date
     *
     * @param strDate   日期字符串
     * @param formatter 日期格式
     * @return 返回两个日期之间间隔的天数
     */
    public static Date dateStrToDate(String strDate, DateTimeFormatter formatter) {
        if (StringUtils.isEmpty(strDate) || formatter == null) {
            return null;
        }

        LocalDateTime dateTime = null;
        Instant instant = null;
        try {
            dateTime = LocalDateTime.parse(strDate, formatter);
            instant = dateTime.atZone(ZoneId.systemDefault()).toInstant();
        } catch (Exception e) {
            LocalDate localDate = LocalDate.parse(strDate, formatter);

            LocalDateTime localDateTime = LocalDateTime.now();

            ZoneId zone = ZoneId.systemDefault();
            instant = localDate.atStartOfDay().atZone(zone).toInstant();
        }
        Date date = Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
        return date;
    }

    /**
     * 查询两个日期之间间隔的天数，仅计算日期，不考虑当日具体时间
     *
     * @param endDate  结束日期
     * @param starDate 开始日
     * @return 返回两个日期之间间隔的天数
     */
    public static Long dateDiff(Date endDate, Date starDate) {
        if (endDate == null || starDate == null) {
            return null;
        }

        Calendar endCal = Calendar.getInstance();
        endCal.setTime(endDate);
        endCal.set(Calendar.HOUR_OF_DAY, 0);
        endCal.set(Calendar.MINUTE, 0);
        endCal.set(Calendar.SECOND, 0);

        Calendar beginCal = Calendar.getInstance();
        beginCal.setTime(starDate);
        beginCal.set(Calendar.HOUR_OF_DAY, 0);
        beginCal.set(Calendar.MINUTE, 0);
        beginCal.set(Calendar.SECOND, 0);
        long days = (endCal.getTimeInMillis() - beginCal.getTimeInMillis()) / (3600 * 24 * 1000);

        return days;
    }

    /**
     * 查询两个日期之间间隔的天数，仅计算日期，不考虑当日具体时间
     *
     * @param endDateStr  结束日期 YYYY-MM-DD
     * @param starDateStr 开始日
     * @return 返回两个日期之间间隔的天数
     */
    public static Long dateDiff(String endDateStr, String starDateStr, String dateFormatStr) {
        if (endDateStr == null || starDateStr == null || dateFormatStr == null) {
            return null;
        }
        //设置转换的日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatStr);
        try {
            Date endDate = dateFormat.parse(endDateStr);
            Date starDate = dateFormat.parse(starDateStr);
            return dateDiff(endDate, starDate);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 查询两个日期之间间隔的天数，仅计算日期，不考虑当日具体时间
     *
     * @param endDateStr  结束日期 YYYY-MM-DD
     * @param starDateStr 开始日
     * @return 返回两个日期之间间隔的天数
     */
    public static Long dateDiff(String endDateStr, String starDateStr) {
        return dateDiff(endDateStr, starDateStr, Constant.DATE_FORMAT_YEAR_MONTH_DAY);
    }

    /**
     * 打印对象所有属性
     *
     * @return 打印对象所有属性字符串
     */
    public static String getFiledString(Object obj) {
        StringBuilder filedString = new StringBuilder();

        Class clazz = obj.getClass();

        //3.getDeclaredFields()获取所有的成员变量，不考虑修饰符
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            try {
                Field field = clazz.getDeclaredField(declaredField.getName());
                if ("serialVersionUID".equals(declaredField.getName())) {
                    continue;
                }
                field.setAccessible(true);//暴力反射
                Object value = field.get(obj);
                filedString.append("," + declaredField.getName());
                filedString.append("=");
                filedString.append(value);

            } catch (NoSuchFieldException e) {
            } catch (IllegalAccessException e) {
            }
        }

        //查找父类
        Class superClazz = clazz.getSuperclass();
        if (null != superClazz) {
            Field[] declaredFieldsParents = superClazz.getDeclaredFields();
            for (Field declaredFieldParent : declaredFieldsParents) {
                try {
                    Field fieldParent = superClazz.getDeclaredField(declaredFieldParent.getName());
                    if ("serialVersionUID".equals(fieldParent.getName())) {
                        continue;
                    }
                    fieldParent.setAccessible(true);//暴力反射
                    Object valueParent = fieldParent.get(obj);
                    filedString.append("," + fieldParent.getName());
                    filedString.append("=");
                    filedString.append(valueParent);
                } catch (NoSuchFieldException e) {
                    logger.error("Error",e);
                } catch (IllegalAccessException e) {
                    logger.error("Error",e);
                }
            }
        }
        if (filedString.indexOf(",") == 0) {
            filedString.deleteCharAt(0);
        }
        filedString.append(" ");

        return filedString.toString();

    }


    /**
     * 获取值为null的属性列表
     * @param source
     * @return
     */
    public static String[] getNullPropertyNames (Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();
        for(PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    /**
     * 获取值为null的属性列表
     * @param source
     * @return
     */
    public static String[] getNullOrEmptyStringPropertyNames (Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();
        for(PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null || StringUtils.isEmpty(srcValue.toString())) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    /**
     * 复制不为空的属性（剔除null字段）
     * @param src
     * @param target
     */
    public static void copyPropertiesIgnoreNull(Object src, Object target){
        BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
    }

    /**
     * 复制不为空的属性（不为null、不是空字符串）
     * @param src
     * @param target
     */
    public static void copyPropertiesIgnoreNullOrEmptyString(Object src, Object target){
        BeanUtils.copyProperties(src, target, getNullOrEmptyStringPropertyNames(src));
    }

    /**
     * 日期类型转换
     * @param date
     * @return
     */
    public static LocalDateTime date2LocalDateTime(Date date) {
        if(null == date) {
            return null;
        }
        return LocalDateTime.ofInstant(date.toInstant(),ZoneId.systemDefault());
    }

    /**
     * 日期类型转换
     * @param localDateTime
     * @return
     */
    public static Date localDateTime2Date(LocalDateTime localDateTime) {
        if(null == localDateTime) {
            return null;
        }
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * 根据日期获取其日期字符串，默认时间格式：yyyy-MM-dd HH:mm:ss
     *
     * @param time 日期
     * @return 日期字符串
     */
    public static String getTimeStr(LocalDateTime time) {
        if(time == null) {
            return "";
        }
        return DictConstant.FORMAT_TIME_DEFAULT2.format(time);
    }


    /**
     * 根据日期获取其日期字符串，默认时间格式：yyyy-MM-dd
     *
     * @param time 日期
     * @return 日期字符串
     */
    public static String getDateStr(LocalDateTime time) {
        return DictConstant.FORMAT_DATE_DEFAULT2.format(time);
    }

    /**
     * 根据日期获取其日期字符串，默认时间格式：yyyy-MM-dd HH:mm:ss
     * @param time 日期
     * @return 日期字符串
     */
    public static String getTimeStr(Date time,SimpleDateFormat format) {
        return format.format(time);
    }

    /**
     * 系统当前日期
     *
     * @return 系统当前日期
     */
    public static String getCurrentDateStr() {
        //设置转换的日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat(Constant.DATE_FORMAT_YEAR_MONTH_DAY);
        return dateFormat.format(new Date());
    }


    /**
     * 比较两个字符串是否相等，如null/空白字符串均为空字符串，相同
     *
     * @param src  源比较字符串
     * @param dest 目标比较字符串
     * @return
     */
    public static boolean strEquals(String src, String dest) {
        if (StringUtils.isEmpty(src)) {
            src = "";
        }
        if (StringUtils.isEmpty(dest)) {
            dest = "";
        }
        src = StringUtils.trim(src);
        dest = StringUtils.trim(dest);

        return src.equalsIgnoreCase(dest) ? true : false;
    }

        /*



    /**
     * 根据日期获取其日期字符串，默认时间格式：yyyy-MM-dd HH:mm:ss
     * @param fileName 可能包含路径的文件名，如C:\Users\TEST20备案资料.pdf，或者仅TEST20备案资料.pdf
     * @return 不含路径的文件名（含文件类型后缀），如TEST20备案资料.pdf
     * @usage :
     应用场景1： MultipartFile的getOriginalFilename，返回的值依赖于浏览器,
     对于IE为带路径如C:\Users\TEST20备案资料.pdf，
     对于chrome为仅含有TEST20备案资料.pdf
    */
    public static String getFileNameFromPath(String fileName){
        String fileNameNoPath=fileName;
        if(StringUtils.isEmpty(fileName)){
            return "";
        }


        //判断是否为IE浏览器的文件名，IE浏览器下文件名会带有盘符信息
        // Check for Unix-style path
        int unixSep = fileName.lastIndexOf('/');

        // Check for Windows-style path
        int winSep = fileName.lastIndexOf('\\');

        // Cut off at latest possible point
        int pos = (winSep > unixSep ? winSep : unixSep);
        if (pos != -1)  {
            // Any sort of path separator found...
            fileNameNoPath = fileName.substring(pos + 1);
        }

        return fileNameNoPath;
    }


    /**
     * 拷贝部分特定属性
     * @param src 源对象
     * @param dest 目标对象
     * @param onlyCopyProps 仅拷贝特定的字段列表
     * @return
     */
    public static void copyPropertiesOnly(Object src, Object dest, Set<String> onlyCopyProps) {
        if (null==onlyCopyProps||onlyCopyProps.size()==0||null==src||null==dest) {
            throw GatewayException.error("拷贝对象特定属性，未指明拷贝的属性列表或者拷贝源、目的对象为NULL");
        }

//        String[] filteredPropertyNames =
//                Arrays.stream(BeanUtils.getPropertyDescriptors(src.getClass()))
//                        .map(PropertyDescriptor::getName)
//                        .filter(onlyCopyProps::contains)
//                        .toArray(String[]::new);
        Set<String> srcFieldSet=getFieldNameList(src.getClass());
        String[] filteredPropertyNames= srcFieldSet.stream().filter(item->!onlyCopyProps.contains(item)).toArray(String[]::new);
        BeanUtils.copyProperties(src, dest, filteredPropertyNames);
    }

    /**
     * 拷贝部分特定属性
     * @param src 源对象
     * @param dest 目标对象
     * @param onlyCopyProps 仅拷贝特定的字段列表
     * @return
     */
    public static void copyPropertiesOnly(Object src, Object dest,String...onlyCopyProps) {
        if (null==onlyCopyProps){
            throw GatewayException.error("拷贝对象特定属性，未指明拷贝的属性列表");
        }

        Set<String> onlyCopyPropSet = new HashSet<>(Arrays.asList(onlyCopyProps));

        copyPropertiesOnly(src,dest,onlyCopyPropSet);
    }

    /**
     * 拷贝除操作信息外的属性
     * @param src 源对象
     * @param dest 目标对象
     * @return
     */
    public static void copyPropertiesIgnoreOpInfo(Object src, Object dest) {

        String[] filteredProperties = new String[]{"opSource","opAction","opOperator","opOperatorName","opTime"};
        BeanUtils.copyProperties(src, dest, filteredProperties);
    }



    /**
     * 检索类的全部属性列表（仅检索类自身以及上一级父类的属性）
     * @param clazz 对象类定义
     * @return
     */
    public static Set<String> getFieldNameList(Class clazz) {
        Set<String> fieldNameSet=null;
        if (null==clazz){
            fieldNameSet=new HashSet<>();
            return fieldNameSet;
        }

        Field[] fields=clazz.getDeclaredFields();

        Field[] superClazzFields=null;
        //查找父类
        Class superClazz = clazz.getSuperclass();
        if (null != superClazz) {
            superClazzFields = superClazz.getDeclaredFields();
            if (null != superClazzFields && superClazzFields.length > 0) {

                Field[] result = Arrays.copyOf(fields, fields.length + superClazzFields.length);

                System.arraycopy(superClazzFields, 0, result, fields.length, superClazzFields.length);

                fields = result;
            }
        }

        fieldNameSet=new HashSet<>(Arrays.asList(Arrays.stream(fields).map(Field::getName).toArray(String[]::new)));

        return fieldNameSet;
    }

    /**
     * 初始化产品名称
     *
     * @param obj        待设置属性值的对象
     * @param fieldName  字段名称
     * @param fieldValue 属性值
     * @return
     */
    public static void setFieldValue(Object obj, String fieldName, Object fieldValue) {
        if (null == obj || StringUtils.isEmpty(fieldName)) {
            return;
        }

        // 获取obj类的字节文件对象
        Class clazz = obj.getClass();
        Type superClazz = clazz.getGenericSuperclass();
        Field field = null;//先从当前类找属性，没有则查找父类
        Method method = null;//父类的setter方法
        try {
            field = clazz.getDeclaredField(fieldName); // 获取该类的成员变量
            field.setAccessible(true);  // 取消语言访问检查
            field.set(obj, fieldValue);  // 给变量赋值
        } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
//            logger.error("对象" + obj.getClass() + "，设置属性" + fieldName + "异常", e);
        } catch (NoSuchFieldException e) {
            try {
//                logger.warn(clazz.toString() + "没有找到属性+" + fieldName + "，尝试父类查找set方法.");
                //尝试使用父类的方法
                if (null != superClazz) {
                    method = ((Class) superClazz).getMethod("set" + CommonUtils.upperFirstChar(fieldName), String.class);
                    method.setAccessible(true);  // 取消语言访问检查
                    method.invoke(obj, fieldValue);
                }
            } catch (SecurityException | IllegalArgumentException | IllegalAccessException e2) {
//                logger.error("对象" + obj.getClass() + "，设置属性" + fieldName + "，查找父类方法异常", e);
            } catch (Exception e2) {
//                logger.error("对象" + obj.getClass() + "，设置属性" + fieldName + "，查找父类方法异常", e);
            }
        }
    }


    /**
     * 获取产品属性的值
     *
     * @param obj       待设置属性值的对象
     * @param fieldName 字段名称
     * @return
     */
    public static Object getFieldValue(Object obj, String fieldName) {
        if (null == obj || StringUtils.isEmpty(fieldName)) {
            return null;
        }

        Object resultFieldValue = null;

        // 获取obj类的字节文件对象
        Class clazz = obj.getClass();
        Type superClazz = clazz.getGenericSuperclass();
        Field field = null;//先从当前类找属性，没有则查找父类
        Method method = null;//父类的setter方法
        try {
            field = clazz.getDeclaredField(fieldName); // 获取该类的成员变量
            field.setAccessible(true);  // 取消语言访问检查
            resultFieldValue = field.get(obj);//获取变量的值
        } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
//            logger.warn("对象" + obj.getClass() + "，设置属性" + fieldName + "异常", e);
        } catch (NoSuchFieldException e) {
            try {
//                logger.warn(clazz.toString() + "没有找到属性+" + fieldName + "，尝试父类查找get方法.");
                //尝试使用父类的方法
                if (null != superClazz) {
                    String getFieldMethodName="get" + CommonUtils.upperFirstChar(fieldName);
                    method = ((Class) superClazz).getMethod(getFieldMethodName);
                    method.setAccessible(true);  // 取消语言访问检查
                    resultFieldValue = method.invoke(obj);

//                    logger.info(clazz.toString() + "没有找到属性+" + fieldName + "，尝试父类查找get方法成功===");
                }
            } catch (SecurityException | IllegalArgumentException | IllegalAccessException e2) {
//                logger.error("对象" + obj.getClass() + "，get属性" + fieldName + "，查找父类方法异常", e);
            } catch (Exception e2) {
//                logger.error("对象" + obj.getClass() + "，get属性" + fieldName + "，查找父类方法异常", e);
            }

        }

        return resultFieldValue;
    }


    //将字符串第一个字母转为大写
    public static String upperFirstChar(String string) {
        char[] chars = string.toCharArray();
        if (chars[0] >= 'a' && chars[0] <= 'z') {
            chars[0] -= 32;
            return String.valueOf(chars);
        }
        return string;
    }


    /**
     * 检查字符串只能是数字和字母组成
     *
     * @param str       待设置属性值的对象
     * @return
     */
    public static boolean isOnlyLetterAndDigit(String str) {
        String regex = "^[a-z0-9A-Z]+$";
        return str.matches(regex);
    }



    /**
     * 获取字符串，如果为空则返回默认值
     *
     * @param str 字符串
     * @param defaultValue 默认值
     * @return
     */
    public static String getString(String str, String defaultValue) {
        return StringUtils.isEmpty(str) ? defaultValue : StringUtils.trim(str);
    }

    /**
     * 获取字符串，如果为空则返回默认值 返回true dateStrOne>=dateStrTwo 返回false dateStrOne < dateStrTwo
     *
     * @param dateStrOne 第一个时间 格式:yyyy-MM-dd
     * @param dateStrTwo 第二个时间 格式:yyyy-MM-dd
     * @return
     */
    public static boolean dateCompareTo(String dateStrOne, String dateStrTwo) {
        boolean res = false;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            res = sdf.parse(dateStrOne).compareTo(sdf.parse(dateStrTwo)) >= 0;
        } catch (Exception e) {
            logger.warn("时间比较异常：", e);
        }
        return res;
    }

    /**
     * 判断产品是否为进TA产品
     *
     * @param prodTaNo 产品TA代码
     * @return
     */
    public static Boolean isTaProd(String prodTaNo) {

        if (StringUtils.isNotEmpty(prodTaNo)) {
            if (DictConstant.PROD_TA_NO_GLSC.equals(prodTaNo)
                    || DictConstant.PROD_TA_NO_GLFW.equals(prodTaNo)
                    || DictConstant.PROD_TA_NO_SZ.equals(prodTaNo)
                    || DictConstant.PROD_TA_NO_SH.equals(prodTaNo)
            ) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断产品是否为集合类产品
     *
     * @param prodType 产品类型
     * @return
     */
    public static Boolean isSetProd(String prodType) {

        if (StringUtils.isNotEmpty(prodType)) {
            if (DictConstant.PROD_TYPE_BIG_SET.equals(prodType)
                    || DictConstant.PROD_TYPE_SMALL_SET.equals(prodType)
                    || DictConstant.PROD_TYPE_PF_BIG_SET.equals(prodType)
            ) {
                return true;
            }
        }
        return false;
    }


    /**
     * 返回JPA或者类似有表字段映射的对象表名称
     *
     * @param clazz 类定义
     * @return
     */
    public static String getTableNameByAnnotation(Class clazz) {
        String tableName = "";
        Annotation tableAnnotation = clazz.getAnnotation(Table.class);
        if (tableAnnotation != null && tableAnnotation instanceof Table) {
            Table realTableAnnotation = (Table) tableAnnotation;
            String annotationTableName = realTableAnnotation.name();
            if (StringUtils.isNotEmpty(annotationTableName)) {
                annotationTableName = StringUtils.trim(annotationTableName).toLowerCase();
                tableName = annotationTableName;
            }
            //TODO 如果有更多的注解标识，可以在这里继续增加；
        }
        return tableName;
    }

    /**
     * 返回JPA或者类似有表字段映射的对象属性列表对应的表字段集合
     *
     * @param
     * @param filterPropSet 过滤属性字段列表
     * @return
     */
    public static Map<String, String> getDomainTableFieldList(Class rootClazz, Set<String> filterPropSet) {
        Map<String, String> tableFieldMap = new HashMap<>();
        if (null == rootClazz) {
            return tableFieldMap;
        }

        //解析表名
        Class clazz = rootClazz;
        String tableName = CommonUtils.getTableNameByAnnotation(clazz);

        //列字段列表
        List<Field> filedList = new ArrayList<>();

        int loopCnt = 0;
        do {
            if (clazz == null || "java.lang.Object".equals(clazz.getName()) || loopCnt++ > 5) {
                break;
            }

            Field[] fields = clazz.getDeclaredFields();
            if (fields != null) {
                filedList.addAll(Arrays.stream(fields).collect(Collectors.toList()));
            }

            //查找父类
            clazz = clazz.getSuperclass();
        } while (clazz != null);

        for (Field field : filedList) {
            if (filterPropSet != null && filterPropSet.size() > 0) {//过滤仅需要返回限定字段
                if (!filterPropSet.contains(field.getName())) {
                    continue;
                }
            }

            Annotation annotation = field.getAnnotation(Column.class);

            if (annotation instanceof Column) {
                Column columnAnnotation = (Column) annotation;
                String tableFieldName = columnAnnotation.name();
                if (StringUtils.isEmpty(tableFieldName)) {

                } else {
                    tableFieldName = StringUtils.trim(tableFieldName).toLowerCase();
                    tableFieldMap.put(tableFieldName, tableName);
                }
                //TODO 如果有更多的注解标识，可以在这里继续增加；
            }
        }
        tableFieldMap.keySet().stream().forEach(item -> System.out.println(item));


        return tableFieldMap;
    }

    /**
     * map转bean
     * @param clazz
     * @param map
     * @return
     * @throws Exception
     */
    public static Object map2JavaBean(Class<?> clazz, Map<String, String> map) throws Exception {
        Object javabean = clazz.newInstance(); // 构建对象
        Method[] methods = clazz.getMethods(); // 获取所有方法
        for (Method method : methods) {
            if (method.getName().startsWith("set")) {
                String field = method.getName(); // 截取属性名
                field = field.substring(field.indexOf("set") + 3);
                field = field.toLowerCase().charAt(0) + field.substring(1);
                if (map.containsKey(field)) {
                    method.invoke(javabean, map.get(field));
                }
            }
        }
        return javabean;
    }

    public static boolean checkEmails(String emails) {
        if (!StringUtils.isEmpty(emails)) {
            List<String> strings = Arrays.asList(emails.split(","));
            for (String s : strings) {
                if (!s.matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$")) {
                    return false;
                }
            }
        }
        return true;
    }

    public static String ListJoin2String(List list){
        return Objects.nonNull(list) ? String.join(",", list) : Strings.EMPTY;
    }

//    jar包冲突
//    /**
//     * 调整excel列宽
//     */
//    public static void setSizeColumn(Sheet sheet, int size) {
//        if (sheet == null || size <= 0) {
//            return;
//        }
//        for (int columnNum = 0; columnNum <= size; columnNum++) {
//            int columnWidth = sheet.getColumnWidth(columnNum) / 256;
//            for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
//                Row currentRow;
//                if (sheet.getRow(rowNum) == null) {
//                    currentRow = sheet.createRow(rowNum);
//                } else {
//                    currentRow = sheet.getRow(rowNum);
//                }
//                if (currentRow.getCell(columnNum) != null) {
//                    Cell currentCell = currentRow.getCell(columnNum);
//                    if (currentCell.getCellType() == CellType.STRING) {
////                    if (currentCell.getCellType() == XSSFCell.CELL_TYPE_STRING) { 3.17版本poi
//                        int length = currentCell.getStringCellValue().getBytes().length;
//                        if (columnWidth < length) {
//                            columnWidth = length;
//                        }
//                    }
//                }
//            }
//            sheet.setColumnWidth(columnNum, columnWidth * 256);
//        }
//    }
}


